/**
 * 
 */
package com.seteam.collabcrossword;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ObjectOutputStream;
import java.util.Collection;

/**
 * Reads the data from the Intra-Client queue and the Inter-client queue and
 * sends the data to the client.
 * 
 * @author SE Team
 * 
 */
public class DataSender extends Thread {
	private final Logger logger = LoggerFactory.getLogger(DataSender.class);

	private ObjectOutputStream out = null;
	private SynchronizedQueue<Object> transferQueue = null;
	private InterClientQueue<Object> interClientQueue = null;
	private final Object mutex;

	/**
	 * Constructor.
	 * 
	 * @param out
	 *            The Output stream of the socket
	 * @param transferQueue
	 *            The intra-client queue between the DataSender and DataReceiver
	 *            of the same Client.
	 * @param mutex
	 *            Used to notify when resource is available in any of the two
	 *            queues(intra-client or inter-client queue)
	 * @param interClientQueue
	 *            The inter-client queue between DataSender of client 1 and the
	 *            DataReceiver of the Client 2.
	 */
	public DataSender(ObjectOutputStream out,
			SynchronizedQueue<Object> transferQueue, Object mutex,
			InterClientQueue<Object> interClientQueue) {
		this.out = out;
		this.transferQueue = transferQueue;
		this.interClientQueue = interClientQueue;
		this.mutex = mutex;

	}

	/**
	 * This is the method that gets called when the start() on the thread is
	 * called. Here a mutex is notified when any data becomes available on any
	 * of the queues. When the data becomes available, this method writes it to
	 * the socket output stream, thus sending data to the client.
	 */
	public void run() {
		while (true) {
			synchronized (mutex) {
				synchronized (this) {
					try {
						// transfer the content of the Intra client queue to the
						// stream.
						if (!transferQueue.isEmpty()) {
							Collection<Object> itemList = transferQueue
									.getAll(true);
							logger.info("Got the objects from the queue");
							for (Object obj : itemList) {
								out.writeObject(obj);
							}
							logger.info("Finished writing objects to output stream");
						}

						// Transfer the contents of the Inter Client queue to
						// the stream.
						if (!interClientQueue.isEmpty()) {
							Collection<Object> itemList = interClientQueue
									.getAll(true);
							logger.info("Got the objects from the inter client queue");
							for (Object obj : itemList) {
								out.writeObject(obj);
							}
							logger.info("Finished writing objects to output stream");
						}

					} catch (Exception e) {
						logger.error("Exception {}", e.getMessage());
					}

				}
			}
		}

	}

}
